from dataclasses import dataclass
from typing import List, Dict, Union, Optional
from pptx.oxml.xmlchemy import OxmlElement
from pptx.enum.text import PP_ALIGN, MSO_ANCHOR
from pptx.util import Inches
from pptx.util import Pt
from pptx.dml.color import RGBColor
@dataclass
class WriteReportEntity:
    position_no: str
    description: str
    nominal_value: float
    unit: str
    upper_tolerance: float
    lower_tolerance: float
    min_val: float  # 避免与内置 min 冲突
    max_val: float  # 避免与内置 max 冲突
    nominal_value_da: float
    upper_tolerance_da: str = "可手动输入"
    lower_tolerance_da: str = "可手动输入"
    comments_remarks: str = ""

# 定义属性与表格列的映射关系（顺序必须一致）
COLUMN_MAPPING = [
    ('NO', 'N0'),
    ('position_no', 'Position No.'),
    ('description', 'Description'),
    ('nominal_value', 'Nominal Value'),
    ('unit', 'Unit'),
    ('upper_tolerance', 'Upper Tolerance'),
    ('lower_tolerance', 'Lower Tolerance'),
    ('min_val', 'Min'),
    ('max_val', 'Max'),
    ('nominal_value_da', 'Nominal Value'),
    ('upper_tolerance_da', 'Upper Tolerance'),
    ('lower_tolerance_da', 'Lower Tolerance'),
    ('comments_remarks', 'Comments/remarks'),
]

def write_excel_table(slide, data: List[WriteReportEntity]):
    # 定义表头结构
    header_structure = [
        # (文本, 起始列, 结束列)
        ("Required value", 2, 6),
        ("Measurement results", 7, 8),
        ("Dimension adjustment", 9, 11)
    ]

    # 创建表格（行数=数据行+2级表头，列数=13）
    rows = len(data) + 3
    cols = 13
    x, y, cx, cy = Inches(0.5), Inches(0.5), Inches(9), Inches(0.25 * rows)
    table = slide.shapes.add_table(rows, cols, x, y, cx, cy).table

    # 设置全局样式
    for cell in table.iter_cells():
        cell.text_frame.paragraphs[0].alignment = PP_ALIGN.CENTER
        cell.vertical_anchor = MSO_ANCHOR.MIDDLE
        cell.fill.solid()
        cell.fill.fore_color.rgb = RGBColor(255, 255, 255)
        tc = cell._tc
        tcPr = tc.get_or_add_tcPr()

        # 调用底层代码设置边框，pptx官网和网上都没现成的方案
        for direction in ['lnL', 'lnR', 'lnT', 'lnB']:  # 左/右/上/下边框
            # 创建边框元素
            ln = OxmlElement(f'a:{direction}')
            ln.set('w', '12700')  # 边框宽度（12700缇≈0.5磅）

            # 创建颜色元素
            solidFill = OxmlElement('a:solidFill')
            srgbClr = OxmlElement('a:srgbClr')
            srgbClr.set('val', '000000')  # 设置颜色值

            # 组装元素
            solidFill.append(srgbClr)
            ln.append(solidFill)

            # 删除旧边框（如果存在）
            existing_ln = tcPr.find(f'{{http://schemas.openxmlformats.org/drawingml/2006/main}}{direction}')
            if existing_ln is not None:
                tcPr.remove(existing_ln)

            tcPr.append(ln)

    cell = table.cell(0, 0)
    cell.merge(table.cell(0, 12))
    cell.text = 'Deviation request list'
    cell.text_frame.paragraphs[0].font.color.rgb = RGBColor(0, 0, 0)  # 黑色字体
    cell.text_frame.paragraphs[0].font.bold = True
    cell.text_frame.paragraphs[0].font.size = Pt(8)
    cell.text_frame.paragraphs[0].alignment = PP_ALIGN.CENTER

    # 绘制第一级表头（合并单元格）
    for text, start_col, end_col in header_structure:
        cell = table.cell(1, start_col)
        cell.text = text
        if start_col != end_col:
            cell.merge(table.cell(1, end_col))

        # 第一级表头样式
        cell.text_frame.paragraphs[0].font.color.rgb = RGBColor(0, 0, 0)  # 黑色字体
        cell.text_frame.paragraphs[0].font.bold = True
        cell.text_frame.paragraphs[0].font.size = Pt(8)
        cell.text_frame.paragraphs[0].alignment = PP_ALIGN.CENTER

        # 填充表头
        for col_idx, (_, header_name) in enumerate(COLUMN_MAPPING):
            cell = table.cell(2, col_idx)
            cell.text = header_name
            cell.text_frame.paragraphs[0].font.bold = True
            cell.text_frame.paragraphs[0].font.size = Pt(8)

        # 填充数据行
        for row_idx, entity in enumerate(data):
            for col_idx, (attr_name, _) in enumerate(COLUMN_MAPPING):
                cell = table.cell(row_idx + 3, col_idx)
                value = getattr(entity, attr_name, row_idx + 1)

                # 数值格式化处理（示例保留2位小数）
                if isinstance(value, (float, int)):
                    cell.text = f"{value:.3f}" if isinstance(value, float) else f"{value}"
                else:
                    cell.text = str(value)

                cell.text_frame.paragraphs[0].font.size = Pt(7)
                cell.fill.fore_color.rgb = RGBColor(255, 255, 255)